#pragma once
#include <iostream>
#include <jsoncpp/json/json.h>

#include "Tool.hpp"
#include "Fields.hpp"
#include "Abstract.hpp"

namespace MyRpc
{

    // 数据 <--> Json 格式相互转换
    class JsonMessage : public BaseMessage
    {
    public:
        using json_msg_ptr = std::shared_ptr<JsonMessage>;

        // 序列化
        std::string Serialize() override
        {
            std::string body;
            bool ret = JsonTool::Serialize(_body, body);
            if (!ret)
            {
                LogArea::LOG(LogLevel::ERROR) << "JsonTool Serialize error: Serialize error";
                return std::string();
            }

            return body;
        }

        // 反序列化
        bool UnSerialize(const std::string &message) override
        {
            bool ret = JsonTool::UnSerialize(message, _body);
            if (!ret)
            {
                LogArea::LOG(LogLevel::ERROR) << "JsonTool UnSerialize error: UnSerialize error";
                return false;
            }
            return true;
        }

    protected:
        Json::Value _body;
    };

    // 请求模块
    class JsonRequest : public JsonMessage
    {
    public:
        using json_req_ptr = std::shared_ptr<JsonRequest>;
    };

    // 响应模块
    class JsonResponse : public JsonMessage
    {
    public:
        using json_rep_ptr = std::shared_ptr<JsonResponse>;
        virtual bool Check() override
        {
            // 在响应中, 大部分的响应只有状态码
            // 因此只需要判断状态码是否存在, 类型是否正确即可
            if (_body[KEY_RCODE].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "JsonReponse Check error: No key_rcode";
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "JsonReponse Check error: key_rcode error";
                return false;
            }
            return true;
        } 

        virtual RCode GetRcode() { return (RCode)_body[KEY_RCODE].asInt(); }         // 获取状态码
        virtual void SetRcode(RCode rcode) { _body[KEY_RCODE] = (int)rcode; } // 设置状态码
    };

    // Rpc请求
    // 包含: Lenth MType idLenth id body
    // body: 请求方法名称--string 请求参数--Json对象
    class RpcRequest : public JsonRequest
    {
    public:
        using rpc_req_ptr = std::shared_ptr<RpcRequest>;
        virtual bool Check() override
        {
            // 请求方法名称不存在 or 请求方法名称类型不正确
            if (_body[KEY_METHOD].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "RpcRequest Check error: No key_method";
                return false;
            }
            if (_body[KEY_METHOD].isString() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "RpcRequest Check error: key_method not string";
                return false;
            }

            // 请求参数不存在 or 请求参数类型不正确
            if (_body[KEY_PARAMS].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "RpcRequest Check error: no key_params";
                return false;
            }
            if (_body[KEY_PARAMS].isObject() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "RpcRequest Check error: key_params not object";
                return false;
            }

            return true;
        }

        std::string GetMethod() { return _body[KEY_METHOD].asString(); }          // 获取请求方法名称
        void SetMethod(const std::string &method) { _body[KEY_METHOD] = method; } // 设置请求方法名称
        Json::Value GetParams() { return _body[KEY_PARAMS]; }                     // 获取请求方法参数
        void SetParams(const Json::Value &params) { _body[KEY_PARAMS] = params; } // 设置请求方法参数
    };

    // Topic请求
    class TopicRequest : public JsonRequest
    {
    public:
        using top_req_ptr = std::shared_ptr<TopicRequest>;
        virtual bool Check() override
        {
            // Topic请求中 主题方法名称不存在 or 主题方法名称类型不正确
            if (_body[KEY_TOPIC_KEY].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "TopicRequest Check error: No key_topic_key";
                return false;
            }
            if (_body[KEY_TOPIC_KEY].isString() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "TopicRequest Check error: key_topic_key not string";
                return false;
            }

            // Topic请求中 主题操作类型不存在 or 操作类型不正确
            if (_body[KEY_OPTYPE].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "TopicRequest Check error: No key_optype";
                return false;
            }
            if (_body[KEY_OPTYPE].isIntegral() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "TopicRequest Check error: key_optype not int";
                return false;
            }

            // 发布消息出错: 发布消息没有消息内容 or 消息内容类型不正确
            if (_body[KEY_OPTYPE].asInt() == (int)TopicOpType::TOPIC_PUBLISH &&
                (_body[KEY_TOPIC_MSG].isNull() || _body[KEY_TOPIC_MSG].isString() == false))
            {
                LogArea::LOG(LogLevel::ERROR) << "TopicRequest Check error: No publish message or publish message not string";
                return false;
            }

            return true;
        }

        std::string GetTopicKey() { return _body[KEY_TOPIC_KEY].asString(); }               // 获取主题方法名称
        void SetTopicKey(const std::string& topic_key) { _body[KEY_TOPIC_KEY] = topic_key; } // 设置主题方法名称
        TopicOpType GetTopicOpType() { return (TopicOpType)_body[KEY_OPTYPE].asInt(); }     // 获取操作类型--返回对象
        void SetTopicOpType(TopicOpType optype) { _body[KEY_OPTYPE] = (int)optype; } // 设置操作类型
        std::string GetTopicMsg() { return _body[KEY_TOPIC_MSG].asString(); }               // 获取主题消息
        void SetTopicMsg(const std::string& message) { _body[KEY_TOPIC_MSG] = message; }     // 设置主题消息
    };

    // Service 请求
    using Address = std::pair<std::string, int>; // Address 就是主机(KEY_HOST)对象
    class ServiceRequest : public JsonRequest
    {
    public:
        using ser_req_ptr = std::shared_ptr<ServiceRequest>;
        virtual bool Check() override
        {
            // Service请求中 请求方法名称不存在 or 请求方法名称类型不正确
            if (_body[KEY_METHOD].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: No key_method";
                return false;
            }
            if (_body[KEY_METHOD].isString() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: key_method not string";
                return false;
            }

            // Service请求中 操作类型不存在 or 操作类型错误
            if (_body[KEY_OPTYPE].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: No key_optype";
                return false;
            }
            if (_body[KEY_OPTYPE].isIntegral() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: key_optype not int";
                return false;
            }

            // Service请求中 主机地址信息错误
            if (_body[KEY_OPTYPE].asInt() != (int)(ServiceOpType::SERVICE_DISCOVERY)) // 不是服务发现操作才进行主机信息判断
            {
                if(_body[KEY_HOST].isNull() || _body[KEY_HOST].isObject() == false)
                {
                    LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: No key_host or key_host not object";
                    return false;
                }
                if (_body[KEY_HOST][KEY_HOST_IP].isNull() || _body[KEY_HOST][KEY_HOST_IP].isString() == false) // 主机Json对象中的 ip 错误
                {
                    LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: No key_host_ip or key_host_ip not string";
                    return false;
                }
                if (_body[KEY_HOST][KEY_HOST_PORT].isNull() || _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false) // 主机 Json对象中的 port 错误
                {
                    LogArea::LOG(LogLevel::ERROR) << "ServiceRequest Check error: No key_host_port or key_host_port not int";
                    return false;
                }
            }
            return true;
        }

        std::string GetMethod() { return _body[KEY_METHOD].asString(); }                        // 获取请求的服务方法名称
        void SetMethod(const std::string& method) { _body[KEY_METHOD] = method; }                // 设置请求的服务方法名称
        ServiceOpType GetServiceOpType() { return (ServiceOpType)_body[KEY_OPTYPE].asInt(); }   // 获取操作类型--返回对象
        void SetServiceOpType(ServiceOpType optype) { _body[KEY_OPTYPE] = (int)optype; } // 设置操作类型

        // 获取主机信息
        Address GetHost()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }

        // 设置主机信息 KEY_HOST: ip port
        void SetHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _body[KEY_HOST] = val;
        }
    };

    // Rpc响应模块
    class RPcResponse : public JsonResponse
    {
    public:
        using rpc_res_ptr = std::shared_ptr<RPcResponse>;
        virtual bool Check() override
        {
            // 响应状态码错误
            if (_body[KEY_RCODE].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: No key_rcode";
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: key_rcode not int";
                return false;
            }

            // 响应结果错误
            if (_body[KEY_RESULT].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: No key_result";
                return false;
            }

            return true;
        }

        Json::Value GetResult() { return _body[KEY_RESULT]; }                     // 获取响应结果
        void SetResult(const Json::Value &result) { _body[KEY_RESULT] = result; } // 设置响应结果
    };

    // 主题响应模块
    class TopicResponse : public JsonResponse
    {
    public:
        using top_res_ptr = std::shared_ptr<TopicResponse>;
    };

    // 服务响应模块
    class ServiceResponse : public JsonResponse
    {
    public:
        using ser_res_ptr = std::shared_ptr<ServiceResponse>;
        virtual bool Check() override
        {
            // 响应状态码错误
            if (_body[KEY_RCODE].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: No key_rcode";
                return false;
            }
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: key_rcode not int";
                return false;
            }

            // 操作类型错误
            if (_body[KEY_OPTYPE].isNull())
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: No key_optype";
                return false;
            }
            if (_body[KEY_OPTYPE].isIntegral() == false)
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: key_optype not int";
                return false;
            }
            // 处理服务发现清空下的错误
            if (_body[KEY_OPTYPE].asInt() == (int)(ServiceOpType::SERVICE_DISCOVERY) &&
                (_body[KEY_METHOD].isNull() || _body[KEY_METHOD].isString() == false || // 响应名称错误
                 _body[KEY_HOST].isNull() || _body[KEY_HOST].isArray() == false))       // 响应主机错误
            {
                LogArea::LOG(LogLevel::ERROR) << "RPcResponse Check error: service_discovery error";
                return false;
            }

            return true;
        }

        // 设置响应的服务器主机信息 可能有多个服务器响应,因此是 vector
        void SetHost(std::vector<Address> addrs)
        {
            for (auto &addr : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = addr.first;
                val[KEY_HOST_PORT] = addr.second;
                _body[KEY_HOST].append(val); // 追加存储所有主机信息
            }
        }

        // 解析 _body[KEY_HOST] 中的所有主机信息并存储
        std::vector<Address> ParseHosts()
        {
            std::vector<Address> addrs;
            int sz = _body[KEY_HOST].size();
            for (int i = 0; i < sz; i++)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                addrs.emplace_back(addr);
            }
            return addrs;
        }

        std::string GetMethod() { return _body[KEY_METHOD].asString(); }                                   // 获取响应方法名称
        void SetMethod(const std::string &method) { _body[KEY_METHOD] = method; }               // 设置响应方法名称
        ServiceOpType GetServiceOpType() { return (ServiceOpType)_body[KEY_OPTYPE].asInt(); }   // 获取操作类型--返回对象
        void SetServiceOpType(ServiceOpType optype) { _body[KEY_OPTYPE] = (int)optype; } // 设置操作类型
    };

    // 消息对象的生产工厂
    class MessageFactory
    {
    public:
        static BaseMessage::msg_ptr create(MType mtype) // 根据操作类型生成不同的消息对象
        {
            switch (mtype)
            {
            case MType::REQ_RPC:
                return std::make_shared<RpcRequest>();
            case MType::RSP_RPC:
                return std::make_shared<RPcResponse>();
            case MType::REQ_TOPIC:
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC:
                return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE:
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE:
                return std::make_shared<ServiceResponse>();
            default:
                LogArea::LOG(LogLevel::ERROR) << "Unknow MessageType";
            }
            return BaseMessage::msg_ptr();
        }

        template<class T,class ...Args>
        static std::shared_ptr<T> create(Args&& ...args)
        {
            return std::make_shared<T>(std::forward(args)...);
        }
    };

}